
let BulletPool = require('GameObjectPool').Bullet;


cc.Class({
    extends: require('BaseComponent'),
    mixins: [cc.EventTarget],

    properties: {
        bulletPrefab: cc.Prefab,

        body: cc.Sprite,

        primaryMuzzle: cc.Node,
        secondaryMuzzle1: cc.Node,
        secondaryMuzzle2: cc.Node,

        secondaryGun1: cc.Sprite,
        secondaryGun2: cc.Sprite,

        powerGroove: cc.Node,
        shield: cc.Sprite,

        container: cc.Node,

        shootSpeed: 0.1,
        bulletDamage: 1,

        x: {
            get() {
                return this.node.x;
            },
            set(val) {
                this.node.x = cc.clampf(val, this.boundaryRange[0] - this.box.x, this.boundaryRange[1] - (this.box.x + this.box.width));
            },
            visible: false
        }
    },

    ctor() {
        this.isShooting = false;
        this._shootInterval = 0;

        this.bulletLines = [];
        this.secondaryGuns = [];

        this.bullets = [];

        this.boundaryRange = [-Infinity, Infinity];

        this.box = cc.rect(0, 0, 0, 0);

        this.collisionChecker = () => true;
    },
    onLoad() {
        BulletPool.setPrefabNode(this.bulletPrefab);

        this.updateBox();

        // Save original values
        this._origValue = {
            shootSpeed: this.shootSpeed,
            bulletDamage: this.bulletDamage,

            grooveSize: this.powerGroove.getContentSize(),
        };


        this.powerGroove.height = 0;
    },
    start() {
        this.addBulletLine();
    },
    update(dt) {
        if (!this.isShooting) return;

        this._shootInterval += dt;
        if (this._shootInterval < this.shootSpeed) return;
        this._shootInterval = 0;

        for (let lineInfo of this.bulletLines) {
            let bulletNode = BulletPool.get();
            let bullet = bulletNode.getComponent('Bullet');
            bullet.damage = this.bulletDamage;

            this.addBulletToContainer(bullet, lineInfo.pos);
        }

        this.emit('shoot-bullet');
    },

    onCollisionEnter(other, self) {
        // cc.log('--AIRSHIP-C-ENTER:',other,self);
        let roadBlock = other.node.getComponent('RoadBlock');
        if (roadBlock) {
            if (this.shield.enabledInHierarchy) return;

            if ( this.collisionChecker(other, self) ) {
                this.emit('hit-block', roadBlock);
            }
            return;
        }

        let item = other.node.getComponent('Item');
        if (item) {
            this.emit('hit-item', item);
        }
    },
    onCollisionExit(other, self) {
        // cc.log('--AIRSHIP-C-EXIT:',other,self);
    },

    reset() {
        this.bulletLines = [];
        this.addBulletLine();

        this.setMuzzlesActive(false);

        for (let idx = 1; idx <= this.secondaryGuns.length; idx++) {
            this['secondaryGun'+ idx].node.active = false;
        }
        this.secondaryGuns = [];

        this.bullets = [];

        this.shootSpeed = this._origValue.shootSpeed;
        this.bulletDamage = this._origValue.bulletDamage;

        this.powerGroove.height = 0;
    },

    shoot() {
        this.isShooting = true;

        this.setMuzzlesActive(true);
    },
    stopShoot() {
        this.isShooting = false;

        this.setMuzzlesActive(false);
    },

    stopAllBullets() {
        for (let bullet of this.bullets) {
            bullet.enabled = false;
        }
    },

    addBulletLine() {
        if (this.bulletLines.length == 5) return;

        let info = {pos: null};
        let count = this.bulletLines.length;
        if (count >= 3) {// primary gun max
            this.bulletLines.push( this.addSecondaryGun() );
        } else {
            this.bulletLines.push(info);

            let posList = [
                [cc.p(0, 0)],
                [cc.p(-30, 0), cc.p(30, 0)],
                [cc.p(-50, 0), cc.p(0, 0), cc.p(50, 0)]
            ][count];

            for (let i = 0; i < posList.length; i++) {
                this.bulletLines[i].pos = cc.pAdd(this.primaryMuzzle.position, posList[i]);
            }
        }
    },
    addSecondaryGun() {
        if (this.secondaryGuns.length == 2) return;

        let idx = this.secondaryGuns.length + 1;
        this['secondaryGun'+ idx].node.active = true;

        let info = {pos: this['secondaryMuzzle'+ idx].position};
        this.secondaryGuns.push(info);

        this['secondaryMuzzle'+ idx].active = this.isShooting;

        let collider = this['secondaryGun'+ idx].getComponent(cc.BoxCollider);
        collider.onCollisionEnter = this.onCollisionEnter.bind(this);

        this.updateBox();

        return info;
    },

    addBulletToContainer(bullet, pos) {
        let container = this.container;

        bullet.node.off('position-changed');
        bullet.position = container.convertToNodeSpaceAR( this.node.convertToWorldSpaceAR(pos) );
        // cc.log('--B-POS:',bullet.__instanceId,bullet.position);
        bullet.node.parent = container;

        bullet.move();

        let downHeight = container.anchorY * container.height,
            upHeight = container.height - downHeight;
        bullet.node.on('position-changed', (event) => {
            if (-downHeight > bullet.y || bullet.y > upHeight) {
                // cc.log('==B-RM:',bullet.__instanceId,BulletPool.size());
                bullet.removeSelf();

                cc.js.array.fastRemoveAt(this.bullets, this.bullets.indexOf(bullet));
            }
        });

        this.bullets.push(bullet);
    },

    setMuzzlesActive(active) {
        this.primaryMuzzle.active = active;

        for (let idx = 1; idx <= this.secondaryGuns.length; idx++) {
            this['secondaryMuzzle'+ idx].active = active;
        }
    },

    useItem(item) {
        let height = this._origValue.grooveSize.height;
        this.powerGroove.height = Math.min(this.powerGroove.height + height/ 6, height);

        if (this.powerGroove.height == height) {// full
            this.emit('fill-power');
        }
    },

    setPowerGroovePercent(percent) {
        this.powerGroove.height = percent * this._origValue.grooveSize.height;
    },

    setShieldActive(active) {
        this.shield.node.active = active;

        if (active) {
            let collider = this.shield.getComponent(cc.CircleCollider);
            collider.onCollisionEnter = (other, self) => {
                let roadBlock = other.node.getComponent('RoadBlock');

                if (roadBlock) {
                    this.emit('hit-shield', roadBlock);
                }
            };
        }
    },

    setBoundary(range) {
        this.boundaryRange = range;
    },

    setCollisionChecker(fn) {
        this.collisionChecker = fn;
    },

    getBox() {
        return cc.rect(this.x + this.box.x, this.y + this.box.y, this.box.width, this.box.height);
    },
    updateBox() {
        let collider = this.getComponent(cc.BoxCollider);
        let rect = cc.rect(
            collider.offset.x - collider.size.width / 2, collider.offset.y - collider.size.height / 2,
            collider.size.width, collider.size.height
        );

        for (let idx = 1; idx <= this.secondaryGuns.length; idx++) {
            let gunSp = this['secondaryGun'+ idx];
            let collider = gunSp.getComponent(cc.BoxCollider);
            let gunRect = cc.rect(
                collider.offset.x - collider.size.width / 2, collider.offset.y - collider.size.height / 2,
                collider.size.width, collider.size.height
            );

            if (idx == 1) {
                gunRect.x += gunSp.node.x;
                rect.width += rect.x - gunRect.x;
                rect.x = gunRect.x;
            } else if (idx == 2) {
                rect.width += gunSp.node.x + (gunRect.x + gunRect.width) - (rect.x + rect.width);
            }
        }

        this.box = rect;
    }
});